package com.chap6;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * <p>
 * <code>SemaphoreDemo2</code>
 * </p>
 *
 * @author junbao3
 * TODO
 * @date 2023-03-17 11:09
 * Copyright (C) 2021 IFlyTek. All rights reserved.
 */
public class SemaphoreDemo2 {
    public static void main(String[] args) {
        final ConnectPool connectPool = new ConnectPool(5);
        ExecutorService executorService = Executors.newCachedThreadPool();

        //5个线程并发竞争资源
        for (int i = 0; i < 100; i++) {
            final  int id = i+1;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    Connect connect = null;
                    try{
                        System.out.println("线程"+id+"等待获取数据库连接");
                        connect = connectPool.openConnect();
                        System.out.println("线程" + id +"已拿到数据库连接："+connect);
                        Thread.sleep(2000);
                        System.out.println("线程" + id +"释放数据库连接："+connect);
                    }catch (Exception e){

                    }finally {
                        connectPool.releaseConnect(connect);
                    }
                }
            });
        }
    }
}


class ConnectPool{
    private int size;
    private Connect[] connects;

    private boolean[] connectFlag;
    private Semaphore semaphore;

    public ConnectPool(int size) {
        this.size = size;
        semaphore=new Semaphore(size,true);
        connects = new Connect[size];
        connectFlag = new boolean[size];
        initConnects();
    }

    private void initConnects() {
        for (int i = 0; i < this.size; i++) {
            connects[i] = new Connect();
        }
    }

    public Connect openConnect() throws InterruptedException {
        semaphore.acquire();
        return getConnect();
    }

    private  Connect getConnect() {
        for (int i = 0; i < connectFlag.length; i++) {
            if (!connectFlag[i]){
                connectFlag[i] = true;
                return connects[i];
            }
        }
        return null;
    }

    public void releaseConnect(Connect connect){
        for (int i = 0; i < this.size; i++) {
            if (connect == connects[i]){
                //释放的时候只是改标记位，池子里面连接对象并没有移除
                connectFlag[i] = false;
                semaphore.release();
            }
        }
    }

}


class Connect{
    private static int count = 1;
    private int id = count++;

    public Connect(){
        //模拟打开链接耗费资源，等待1秒
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("连接#" + id + "#已与数据库建立通道！");
    }

    @Override
    public String toString() {
        return "#" + id + "#";
    }
}
